<?php

namespace App\Kits\Repository;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\User;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Laravel\Passport\ClientRepository;
use Laravel\Passport\TokenRepository;
use Lcobucci\JWT\Parser;
use Lcobucci\JWT\Token;

/**
 * Token管理
 * Class LibTokenRepository
 * @package App\Kits\Repository;
 */
class LibTokenRepository extends TokenRepository
{
    public $token;
    public $request;
    public $bearerToken = '';
    public $tokenRepository;
    public $clientRepository;

    public function __construct(Request $request, ClientRepository $clientRepository, TokenRepository $tokenRepository)
    {
        $this->request = $request;
        $this->tokenRepository = $tokenRepository;
        $this->clientRepository = $clientRepository;
    }

    /**
     * 获取个人用户端
     * @return \Laravel\Passport\Client|null
     */
    public function getClient()
    {
        $token = $this->getToken();
        if (!$token) {
            return null;
        }
        return $this->clientRepository->find($token->getClaim('aud', 0));
    }

    /**
     * 获取登录用户
     * @param Model $model
     * @return User|null
     */
    public function getUser(Model $model): ?User
    {
        $token = $this->getToken();
        if (!$token) {
            return null;
        }
        return $model->where('id', $token->getClaim('sub', 0))->first();
    }

    /**
     * 获取token实体
     * @return \Laravel\Passport\Token|null
     */
    public function getTokenEntity()
    {
        $token = $this->getToken();
        if (!$token) {
            return null;
        }
        return $this->tokenRepository->find($token->getClaim('jti', 0));
    }

    /**
     * 判断token的刷新时间是否已经过期
     * @return bool
     */
    public function isRefreshExpired()
    {
        $token = $this->getToken();
        if (!$token) {
            return true;
        }
        $tokenEntity = $this->getTokenEntity();
        if (!$tokenEntity) {
            return true;
        }
        if ($tokenEntity->revoked) { //token已被主动设为过期
            return true;
        }
        return $tokenEntity->refresh_at < new \DateTime();
    }

    /**
     * 使当前token失效
     * @return bool|null
     * @throws \Exception
     */
    public function setTokenRevoked()
    {
        $tokenEntity = $this->getTokenEntity();
        if ($tokenEntity) {
            if ($tokenEntity->expires_at < new \DateTime()) { // Token已过期
                return $tokenEntity->delete();
            }
            $tokenEntity->revoked = true;
            return $tokenEntity->save();
        }
    }

    /**
     * 获取token实例
     * @return Token|null
     */
    public function getToken(): ?Token
    {
        if (!$this->token) {
            $bearerToken = $this->getBearerToken($this->request);
            if ($bearerToken) {
                $jwt = trim((string)preg_replace('/^(?:\s+)?Bearer\s/', '', $bearerToken));
                $this->token = (new Parser())->parse($jwt);
            }
        }
        return $this->token;
    }

    /**
     * 通过Request对象获取BearerToken
     * @param Request $request
     * @return string
     */
    public function getBearerToken(Request $request): string
    {
        if (empty($this->bearerToken)) {
            $token = $request->server->get('HTTP_AUTHORIZATION', '');
            if (Str::startsWith($token, 'Bearer ')) {
                $this->bearerToken = Str::substr($token, 7);
            }
        }
        return $this->bearerToken;
    }
}
